//
// Created by feng on 19-3-28.
// PS: Define the receiver data structure.
//

#ifndef SOLARENERGY_CHIER_RECEIVER_CUH
#define SOLARENERGY_CHIER_RECEIVER_CUH

#include <cuda_runtime.h>

namespace solar::cuda
{
    class CudaReceiver
    {
        public:
            /**
             * Initialize the parameters.
             */
            virtual void CInit(float pixel_per_meter_for_receiver) = 0;
            virtual void Cset_resolution(float pixel_per_meter_for_receiver) = 0;
            virtual auto getFocusCenter(const float3& heliostat_position) -> float3 = 0;

            /**
             * Allocate the final image matrix.
             */
            void Calloc_image();

            /**
             * Clean the final image matrix.
             */
            void Cclean_image_content();

            void CClear();

            __device__ __host__ CudaReceiver() = default;

            __device__ __host__ CudaReceiver(const CudaReceiver& rec) = default;

            __device__ __host__ virtual ~CudaReceiver() = default;

            /**
             * Getters and setters of attributes for receiver object.
             */
            [[nodiscard]] auto getType() const -> int;
            void setType(int type_);

            void setRadius(float radius_);

            auto getTubeUnit() const -> int;
            void setTubeUnit(int tubeUnit_);

            auto getTube() const -> int;
            void setTube(int tube_);

            auto getPanel() const -> int;
            void setPanel(int panel_);

            [[nodiscard]] auto getNormal() const -> float3;
            void setNormal(float3 normal);

            [[nodiscard]] auto getPosition() const -> float3;
            void setPosition(float3 pos);

            [[nodiscard]] auto getSize() const -> float3;
            void setSize(float3 size_);

            [[nodiscard]] auto getSurfaceIndex() const -> int;
            void setSurfaceIndex(int surface_index);

            [[nodiscard]] auto getPixelLength() const -> float;
            __host__ __device__ auto getDeviceImage() const -> float* { return d_image_; }
            __host__ __device__ auto getRadius() const -> float { return radius_; }
            __host__ __device__ auto getDeviceTotal() const -> float* { return d_total_reflect_; }
            __host__ __device__ auto getResolution() const -> int2 { return resolution_; }

            int type_; // rectangle receiver:0   cylinder receiver:1
            float3 normal_;
            float3 pos_;
            float3 size_;
            int surface_index_; // the index of receiving surface
            float pixel_length_; // --------又定义类一个pixel_length，与sceneConfiguration重复了
            float* d_image_{}; // On GPU, memory size = resolution_.x * resolution_.y
            int2 resolution_;  // x means column, y means row
            float* d_total_reflect_{};
            float radius_; // cylinder radius
            int tubeUnit_;
            int tube_;
            int panel_;
            cudaStream_t stream_ = nullptr;
    };
} // namespace solar::cuda

#endif // SOLARENERGY_CHIER_RECEIVER_CUH
